package com.zxl.security;

import com.zxl.security.core.social.properties.SecurityConstants;
import com.zxl.security.core.social.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.servlet.Filter;

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private SpringSocialConfigurer springSocialConfigurer;
    @Autowired
    private InvalidSessionStrategy invalidSessionStrategy;
    @Autowired
    private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;
    @Autowired
    private Filter validateCodeFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)// 跳转到我们制定的登录处理页面或者登录处理url
                .loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)//  处理我们的登录提交的数据url，这个是spring security帮我们进行处理的，我们只需要配置想要的url地址即可
                .successHandler(authenticationSuccessHandler)// 登录成功的处理器
                .failureHandler(authenticationFailureHandler)// 登录失败的处理器
            .and()
                .authorizeRequests()// 对请求进行授权
                .antMatchers(
                        SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                        securityProperties.getBrowser().getLoginPage(),
                        securityProperties.getBrowser().getSignUpUrl(),
                        securityProperties.getBrowser().getSession().getSessionInvalidUrl() + ".json",
                        securityProperties.getBrowser().getSession().getSessionInvalidUrl() + ".html",
                        "/user/register",
                        "/auth.html",
                        SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/*")// 设置匹配这个url的地址
                .permitAll()// 设置上面匹配的地址不需要进行授权
                .anyRequest()// 任意请求
                .authenticated()// 需要授权
            .and()
                .apply(springSocialConfigurer)
            .and()
                .sessionManagement()
                .invalidSessionStrategy(invalidSessionStrategy)
                .invalidSessionUrl(securityProperties.getBrowser().getSession().getSessionInvalidUrl())// session失效后跳转的url
                .maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
                .maxSessionsPreventsLogin(securityProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())// 设置为true后意味着如果登录用户达到会话最大数量，阻止用户进行登录
                .expiredSessionStrategy(sessionInformationExpiredStrategy)
                .and()
            .and()
                .logout()
                .logoutUrl("/logout")// 定义请求退出登录的url地址
                .logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies("JSESSIONID")
            .and()
                .csrf().disable();
    }
}
